<?php
class BuildAclsController extends AppController {

    var $name = 'BuildAcls';
    var $appModule = 'Seguridad';
    var $uses = array();

    var $allowedMethods = array('add', 'ajax', 'cancel', 'delete', 'edit', 'execute', 'print', 'imprimir',
            'liquidar', 'manager', 'process', 'serie', 'sumar', 'view');
    var $acos = array();

    function build() {
		if (!Configure::read('debug')) {
			return $this->_stop();
		}
                ini_set("memory_limit","20M");
		$log = array();
                ini_set("memory_limit","20M");

		$acoModel =& $this->Acl->Aco;

		App::import('Core', 'File');
		$Controllers = Configure::listObjects('controller');
		$appIndex = array_search('App', $Controllers);
		if ($appIndex !== false ) {
			unset($Controllers[$appIndex]);
		}
		$baseMethods = get_class_methods('AppController');
		$baseMethods[] = 'buildAcl';

		$Plugins = $this->_getPluginControllerNames();
		$Controllers = array_merge($Controllers, $Plugins);

		$id = 1;
		$parent = null;
		$acos =& $this->acos;

		// look at each controller in app/controllers
		foreach ($Controllers as $ctrlName) {
			$methods = $this->_getClassMethods($this->_getPluginControllerPath($ctrlName));
			$appModule = $this->_getClassAppModule($this->_getPluginControllerPath($ctrlName));
			if (empty($appModule)) continue;
			$appModule = up($appModule);
			$appModuleNode = $this->_find($appModule);
			if (empty($appModuleNode)) {
				$data['Modulo']['id']=$id;
				$data['Modulo']['parent_id']=null;
				$data['Modulo']['model']=null;
				$data['Modulo']['foreign_key']=null;
				$data['Modulo']['alias']=$appModule;

				$acos[$id] = $data;
				$data = array();
				$parent = $id;
				$id++;
			} else {
				$parent = $appModuleNode['Modulo']['id'];
			}
			// find / make controller node
			$controllerNode = $this->_find($ctrlName, $parent);
			if (!$controllerNode) {
				if ($this->_isPlugin($ctrlName)){
						$pluginNode = $aco->node($appModule.'/' . $this->_getPluginName($ctrlName));
						$ctrlName = $this->_getPluginControllerName($ctrlName);
				}

				$data['id']=$id;
				$data['parent_id']=$parent;
				$data['model']=null;
				$data['foreign_key']=null;
				$data['alias']=$ctrlName;

				$acos[$parent]['Controlador'][$id] = $data;
				$data = array();
				$parentc = $id;
				$id++;
			} else {
				$parentc = $controllerNode['Controlador']['id'];
			}
			//clean the methods. to remove those in Controller and private actions.
			foreach ($methods as $k => $method) {
				if (strpos($method, '_', 0) === 0) {
					unset($methods[$k]);
					continue;
				}

				if (in_array($method, $baseMethods)) {
					unset($methods[$k]);
					continue;
				}

				$methodNode  = $this->_find($method, $parentc);
				if (empty($methodNode)) {
					$data['id']=$id;
					$data['parent_id']=$parentc;
					$data['model']=null;
					$data['foreign_key']=null;
					$data['alias']=$method;

					$acos[$parent]['Controlador'][$parentc]['Metodo'][$id] = $data;
					$data = array();
					$id++;
				} else continue;
			}
		}

		$lft = 1;
		foreach($acos as &$aco){
			$acos[$aco['Modulo']['id']]['Modulo']['lft'] = $lft++;
			foreach($aco['Controlador'] as &$ctrl){
				$acos[$aco['Modulo']['id']]['Controlador'][$ctrl['id']]['lft'] = $lft++;
				if (array_key_exists('Metodo', $ctrl))
					foreach($ctrl['Metodo'] as &$metodo){
						$acos[$aco['Modulo']['id']]['Controlador'][$ctrl['id']]['Metodo'][$metodo['id']]['lft'] = $lft++;
						$acos[$aco['Modulo']['id']]['Controlador'][$ctrl['id']]['Metodo'][$metodo['id']]['rght'] = $lft++;
					}
				$acos[$aco['Modulo']['id']]['Controlador'][$ctrl['id']]['rght'] = $lft++;
			}
			$acos[$aco['Modulo']['id']]['Modulo']['rght'] = $lft++;
		}

		foreach($acos as &$aco){
			$acoModel->create($aco['Modulo']);
			$acoModel->save();
			foreach($aco['Controlador'] as &$ctrl){
				$acoModel->create($ctrl);
				$acoModel->save();
				if (array_key_exists('Metodo', $ctrl))
					foreach($ctrl['Metodo'] as &$metodo){
						$acoModel->create($metodo);
						$acoModel->save();
					}
			}
		}

		echo '<pre>';
		print_r($acos);
		echo '</pre>';
		exit;
	}


	function update(){
		set_time_limit(0);

		if (!Configure::read('debug')) {
			return $this->_stop();
		}
		$log = array();
                ini_set("memory_limit","20M");

		$acoModel =& $this->Acl->Aco;

		App::import('Core', 'File');
		$Controllers = Configure::listObjects('controller');
		$appIndex = array_search('App', $Controllers);
		if ($appIndex !== false ) {
			unset($Controllers[$appIndex]);
		}
		$baseMethods = get_class_methods('AppController');
		$baseMethods[] = 'buildAcl';

		$Plugins = $this->_getPluginControllerNames();
		$Controllers = array_merge($Controllers, $Plugins);

		//$id = 1;
		$parent = null;
		$acos =& $this->acos;
		$indice = $acoModel->find('first',array(
						'fields'=>array('Aco.id'),
						'order'=>array('Aco.id'=>'desc'),
						'recursive'=>-1));
		$indice = $indice['Aco']['id'];

		$__control = array();
		// look at each controller in app/controllers
		foreach ($Controllers as $ctrlName) {
			$methods = $this->_getClassMethods($this->_getPluginControllerPath($ctrlName));
			$appModule = trim($this->_getClassAppModule($this->_getPluginControllerPath($ctrlName)));
			if (empty($appModule)) continue;
			$appModule = up($appModule);
			$appModuleNode = $this->_find($appModule);
//			var_dump($appModuleNode);die;
			if (empty($appModuleNode)) {
				$_appModuleNode = $acoModel->find('first', array(
                                    'conditions'=>array('upper(alias)'=>$appModule, 'parent_id'=>null),
                                    'recursive'=>-1
                                ));
				if(!empty($_appModuleNode['Aco']['id'])){
					$id = $_appModuleNode['Aco']['id'];
					$create = false;
				} else {
					$id = ++$indice;
					$create = true;
				}
				$parent = $id;

				$data['Modulo']['id'] = $id;
				$data['Modulo']['parent_id'] = null;
				$data['Modulo']['model'] = null;
				$data['Modulo']['foreign_key'] = null;
				$data['Modulo']['alias'] = $appModule;
				$data['Modulo']['create'] = $create;

				$acos[$id] = $data;
				$data = array();
				$parent = $id;

				//$id++;

			 }  else {
				$parent = $appModuleNode['Modulo']['id'];
			}
			// find / make controller node

			$controllerNode = $this->_find($ctrlName, $parent);
			if (!$controllerNode) {
				if ($this->_isPlugin($ctrlName)){
					$pluginNode = $aco->node($appModule.'/' . $this->_getPluginName($ctrlName));
					$ctrlName = $this->_getPluginControllerName($ctrlName);
				}

				$controller = $acoModel->find('first', array( // el nombre del controlador es unico
                                    'conditions'=>array('alias'=>$ctrlName),
                                    'recursive'=>-1
                                ));
				if(!empty($controller['Aco']['id'])){
					$id = $controller['Aco']['id'];
					$create = false;
				} else {
					$id = ++$indice;
					$create = true;
				}

				$data['id'] = $id;
				$data['parent_id'] = $parent;
				$data['model'] = null;
				$data['foreign_key'] = null;
				$data['alias'] = $ctrlName;
				$data['create'] = $create;

				$acos[$parent]['Controlador'][$id] = $data;
				array_push($__control, $data);
				$data = array();
				$parentc = $id;
				//$id++;
			} else {
				$parentc = $controllerNode['id'];
			}
			//clean the methods. to remove those in Controller and private actions.
			foreach ($methods as $k => $method) {
					if (strpos($method, '_', 0) === 0) {
							unset($methods[$k]);
							continue;
					}
					if (in_array($method, $baseMethods)) {
							unset($methods[$k]);
							continue;
					}
					$methodNode  = $this->_find($method, $parentc);
					if (empty($methodNode)) {
							$metodo = $acoModel->find('first', array(
                                                            'conditions'=>array('alias'=>$method,'parent_id'=>$parentc),
                                                            'recursive'=>-1
                                                        ));
							if(!empty($metodo['Aco']['id'])){
								$id = $metodo['Aco']['id'];
								$create = false;
							} else {
								$id = ++$indice;
								$create = true;
							}

							$data['id']=$id;
							$data['parent_id']=$parentc;
							$data['model']=null;
							$data['foreign_key']=null;
							$data['alias']=$method;
							$data['create'] = $create;

							$acos[$parent]['Controlador'][$parentc]['Metodo'][$id] = $data;
							$data = array();
					} else continue;
			}
		}
		$lft = 1;
		foreach($acos as &$aco){
			$acos[$aco['Modulo']['id']]['Modulo']['lft'] = $lft++;
			foreach($aco['Controlador'] as &$ctrl){
				$acos[$aco['Modulo']['id']]['Controlador'][$ctrl['id']]['lft'] = $lft++;
				if (array_key_exists('Metodo', $ctrl))
					foreach($ctrl['Metodo'] as &$metodo){
						$acos[$aco['Modulo']['id']]['Controlador'][$ctrl['id']]['Metodo'][$metodo['id']]['lft'] = $lft++;
						$acos[$aco['Modulo']['id']]['Controlador'][$ctrl['id']]['Metodo'][$metodo['id']]['rght'] = $lft++;
					}
				$acos[$aco['Modulo']['id']]['Controlador'][$ctrl['id']]['rght'] = $lft++;
			}
			$acos[$aco['Modulo']['id']]['Modulo']['rght'] = $lft++;
		}

                $acoModel->begin();
		foreach($acos as &$aco){
			if($aco['Modulo']['create']){
				$acoModel->create();
			}
			$acoModel->save($aco['Modulo']);
//                        echo 'modulo '.$aco['Modulo']['id'].'<br>';
			foreach($aco['Controlador'] as &$ctrl){
				if($ctrl['create']){
					$acoModel->create();
				}
//                                echo 'controller '.$ctrl['id'].'<br>';
				$acoModel->save($ctrl);
				if (array_key_exists('Metodo', $ctrl))
					foreach($ctrl['Metodo'] as &$metodo){
						if($metodo['create']){
							$acoModel->create();
						}
						$acoModel->save($metodo);
//                                                echo 'metodo '.$metodo['id'].'<br>';
					}
			}
		}
//                $acoModel->rollback();
                $acoModel->commit();
//		echo '<pre>';
//		print_r($acos);
//		echo '</pre>';
		exit;
	}

    function _find($alias, $parent = null){
		foreach($this->acos as $a){
			if (array_key_exists('Modulo', $a)){
				if ($a['Modulo']['alias']==$alias)
						return $a;
			}
			if (array_key_exists('Controlador', $a)){
				foreach($a['Controlador'] as $k){
					if ($k['alias']==$alias && $k['parent_id']==$parent)
							return $k;
					if (array_key_exists('Metodo', $k)){
						foreach($k['Metodo'] as $m){
							if ($m['alias']==$alias && $m['parent_id']==$parent)
									return $m;
						}
					}
				}
			}
		}
		return null;
	}

	function _getClassMethods($ctrlName = null) {
		App::import('Controller', $ctrlName);
		if (strlen(strstr($ctrlName, '.')) > 0) {
			// plugin's controller
			$num = strpos($ctrlName, '.');
			$ctrlName = substr($ctrlName, $num+1);
		}
		$ctrlclass = $ctrlName . 'Controller';
		$methods = get_class_methods($ctrlclass);

		// Add scaffold defaults if scaffolds are being used
		$properties = get_class_vars($ctrlclass);
//		if (is_array($properties) && array_key_exists('scaffold',$properties)) {
//			if($properties['scaffold'] == 'admin') {
//				$methods = array_merge($methods, array('admin_add', 'admin_edit', 'admin_index', 'admin_view', 'admin_delete'));
//			} else {
//				$methods = array_merge($methods, array('add', 'edit', 'index', 'view', 'delete'));
//			}
//		}
		return $methods;
	}

	function _getClassAppModule($ctrlName = null) {
		App::import('Controller', $ctrlName);
		if (strlen(strstr($ctrlName, '.')) > 0) {
                    // plugin's controller
                    $num = strpos($ctrlName, '.');
                    $ctrlName = substr($ctrlName, $num+1);
		}
		$ctrlclass = $ctrlName . 'Controller';
		// Add scaffold defaults if scaffolds are being used
		$properties = get_class_vars($ctrlclass);
                //debug($properties);
		if (is_array($properties) && array_key_exists('appModule',$properties)) {
                    return $properties['appModule'];
		}
                else return null;
	}

	function _isPlugin($ctrlName = null) {
		$arr = String::tokenize($ctrlName, '/');
		if (count($arr) > 1) {
			return true;
		} else {
			return false;
		}
	}

	function _getPluginControllerPath($ctrlName = null) {
		$arr = String::tokenize($ctrlName, '/');
		if (count($arr) == 2) {
			return $arr[0] . '.' . $arr[1];
		} else {
			return $arr[0];
		}
	}

	function _getPluginName($ctrlName = null) {
		$arr = String::tokenize($ctrlName, '/');
		if (count($arr) == 2) {
			return $arr[0];
		} else {
			return false;
		}
	}

	function _getPluginControllerName($ctrlName = null) {
		$arr = String::tokenize($ctrlName, '/');
		if (count($arr) == 2) {
			return $arr[1];
		} else {
			return false;
		}
	}

/**
 * Get the names of the plugin controllers ...
 *
 * This function will get an array of the plugin controller names, and
 * also makes sure the controllers are available for us to get the
 * method names by doing an App::import for each plugin controller.
 *
 * @return array of plugin names.
 *
 */
	function _getPluginControllerNames() {
		App::import('Core', 'File', 'Folder');
		$paths = Configure::getInstance();
		$folder =& new Folder();
		$folder->cd(APP . 'plugins');

		// Get the list of plugins
		$Plugins = $folder->read();
		$Plugins = $Plugins[0];
		$arr = array();

		// Loop through the plugins
		foreach($Plugins as $pluginName) {
			// Change directory to the plugin
			$didCD = $folder->cd(APP . 'plugins'. DS . $pluginName . DS . 'controllers');
			// Get a list of the files that have a file name that ends
			// with controller.php
			$files = $folder->findRecursive('.*_controller\.php');

			// Loop through the controllers we found in the plugins directory
			foreach($files as $fileName) {
				// Get the base file name
				$file = basename($fileName);

				// Get the controller name
				$file = Inflector::camelize(substr($file, 0, strlen($file)-strlen('_controller.php')));
				if (!preg_match('/^'. Inflector::humanize($pluginName). 'App/', $file)) {
					if (!App::import('Controller', $pluginName.'.'.$file)) {
						debug('Error importing '.$file.' for plugin '.$pluginName);
					} else {
						/// Now prepend the Plugin name ...
						// This is required to allow us to fetch the method names.
						$arr[] = Inflector::humanize($pluginName) . "/" . $file;
					}
				}
			}
		}
		return $arr;
	}
}
?>
